package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.commons.utils.DateConversionUtils;
import com.tanhua.dubbo.api.*;
import com.tanhua.model.db.*;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @auther : 白月尘
 * @date : 16:52  2021/10/20
 */
@Service
public class MovementsService {
    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementTimeLineApi movementTimeLineApi;

    @DubboReference
    private UserInfoApi userInfoApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private MqMessageService mqMessageService;
    @DubboReference
    private CommentApi commentApi;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    @DubboReference
    private FreezeApi freezeApi;

    public PageResult initPage(List<Movement> list, Integer page, Integer pageSize) {
        if (list == null || list.size() <= 0) {
            return new PageResult();
        }
        List<Long> userInfoList = CollUtil.getFieldValues(list, "userId", long.class);
        Map<Long, UserInfo> map = userInfoApi.findAll(userInfoList);
        List<MovementsVo> MovementsVoList = new ArrayList<>();
        for (Movement movement : list) {
            UserInfo userInfo = map.get(movement.getUserId());
            MovementsVo init = MovementsVo.init(userInfo, movement);
            String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
            String hashLikeKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            String hashLoveKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
            Boolean likeKey = redisTemplate.opsForHash().hasKey(redisKey, hashLikeKey);
            if (likeKey) {
                init.setHasLiked(1);
            }
            Boolean loveKey = redisTemplate.opsForHash().hasKey(redisKey, hashLoveKey);
            if (loveKey) {
                init.setHasLoved(1);
            }
            MovementsVoList.add(init);
        }
        return new PageResult(page, pageSize, 0l, MovementsVoList);
    }

    public void movements(String textContent, MultipartFile[] imageContents) {
        try {
            List<String> list = new ArrayList();
            for (MultipartFile imageContent : imageContents) {
                String upload = ossTemplate.upload(imageContent.getOriginalFilename(), imageContent.getInputStream());
                list.add(upload);
            }
            Movement movement = new Movement();
            movement.setUserId(UserHolder.getUserId());
            movement.setCreated(System.currentTimeMillis());
            movement.setTextContent(textContent);
            movement.setMedias(list);
            String movementId = movementApi.save(movement);
            mqMessageService.sendAudiService(movementId);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public PageResult findByUserId(Integer page, Integer pageSize, Long userId) {
        List<Movement> movements = movementApi.findByUserId(page, pageSize, userId);
        return initPage(movements, page, pageSize);
    }

    //好友动态
    public PageResult findByFriendId(Integer page, Integer pageSize) {
        List<Movement> list = movementApi.findByFriendId(page, pageSize, UserHolder.getUserId());
        return initPage(list, page, pageSize);
    }

    public PageResult recommend(Integer page, Integer pageSize) {
        String key = "MOVEMENTS_RECOMMEND_" + UserHolder.getUserId();
        String value = redisTemplate.opsForValue().get(key);
        List<Movement> list = new ArrayList<>();
        if (StrUtil.isEmpty(value)) {
            list = movementApi.randomMovements(pageSize);
        } else {
            String[] strings = value.split(",");
            list = movementApi.findByIds(page, pageSize, strings);
        }
        return initPage(list, page, pageSize);
    }


    public MovementsVo findById(String id) {
        Movement movement = movementApi.findById(id);
        UserInfo userInfo = userInfoApi.findById(movement.getUserId());
        MovementsVo movementsVo = MovementsVo.init(userInfo, movement);
        return movementsVo;
    }


    public Integer like(String id) {
        //调用API查询是否对动态点赞
        boolean hasComment = commentApi.hasComment(id, UserHolder.getUserId(), 1);
        if (hasComment) {
            throw new BusinessException(ErrorResult.likeError());
        }
        //调用API保存互动数据
        Comment comment1 = new Comment();
        comment1.setPublishId(new ObjectId(id));
        comment1.setCreated(System.currentTimeMillis());
        comment1.setCommentType(1);
        comment1.setUserId(UserHolder.getUserId());
        Integer i = commentApi.save(comment1);
        //在redis中记录点赞状态
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + id;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");
        mqMessageService.sendLogService(UserHolder.getUserId(),"0203","movement",id);
        return i;
    }

    public Integer dislike(String id) {
        //判断是否点赞
        boolean hasComment = commentApi.hasComment(id, UserHolder.getUserId(), 1);
        //1.查询是否已经点赞,如果已点赞抛出异常
        if (!hasComment) {
            //2.如果未点赞,抛出异常
            throw new BusinessException(ErrorResult.disLikeError());
        }
        //3.如果已点赞,删除mongo数据,redis数据
        Integer i = commentApi.delete(id, UserHolder.getUserId(), 1);
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + id;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(redisKey, hashKey);
        mqMessageService.sendLogService(UserHolder.getUserId(),"0206","movement",id);
        return i;
    }

    public Integer love(String id) {
        //调用API查询是否对动态喜欢
        boolean hasComment = commentApi.hasComment(id, UserHolder.getUserId(), 3);
        if (hasComment) {
            throw new BusinessException(ErrorResult.loveError());
        }
        //调用API保存互动数据
        Comment comment1 = new Comment();
        comment1.setPublishId(new ObjectId(id));
        comment1.setCreated(System.currentTimeMillis());
        comment1.setCommentType(3);
        comment1.setUserId(UserHolder.getUserId());
        Integer i = commentApi.save(comment1);
        //在redis中记录点赞状态
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + id;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");
        mqMessageService.sendLogService(UserHolder.getUserId(),"0204","movement",id);
        return i;
    }

    public Integer unlove(String id) {
        //判断是否点赞
        boolean hasComment = commentApi.hasComment(id, UserHolder.getUserId(), 3);
        //1.查询是否已经点赞,如果已点赞抛出异常
        if (!hasComment) {
            //2.如果未点赞,抛出异常
            throw new BusinessException(ErrorResult.disloveError());
        }
        //3.如果已点赞,删除mongo数据,redis数据
        Integer i = commentApi.delete(id, UserHolder.getUserId(), 3);
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + id;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(redisKey, hashKey);
        mqMessageService.sendLogService(UserHolder.getUserId(),"0207","movement",id);
        return i;
    }


    public List<TodayBest> visitors() {
        String key = Constants.VISITORS_USER + UserHolder.getUserId();
        String s = redisTemplate.opsForValue().get(key);
        Long time = 0l;
        if (!StringUtils.isEmpty(s)) {
            time = Long.parseLong(s);
        }
        List<Visitors> visitorsList = visitorsApi.findByUserId(UserHolder.getUserId(), time);
        if (visitorsList == null || visitorsList.size() <= 0) {
            return new ArrayList<>();
        }
        List<Long> visitorUserId = CollUtil.getFieldValues(visitorsList, "visitorUserId", long.class);
        List<TodayBest> vos = new ArrayList<>();
        Map<Long, UserInfo> map = userInfoApi.findAll(visitorUserId);
        for (Visitors visitors : visitorsList) {
            UserInfo userInfo = map.get(visitors.getVisitorUserId());
            TodayBest vo = TodayBest.init(userInfo, visitors);
            vos.add(vo);
        }
        return vos;
    }
    public void checkFreezeState(Long userId, String textContent, MultipartFile[] imageContents) {

        Freeze freeze = freezeApi.selectByUid(userId);
        if (freeze == null) {
            this.movements(textContent, imageContents);
        }
        // 冻结范围：1为冻结登录，2为冻结发言，3为冻结发布动态
        if (freeze != null && freeze.getFreezingRange() == 3) {
            Date currentDate = DateConversionUtils.parseStrToDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                    .format(new Date()), "yyyy-MM-dd HH:mm:ss", new Date());
            Date unfreezeTime = freeze.getUnfreezeTime();
            Long timeDifference = freezeApi.selectFreezeTimeDifference(currentDate, unfreezeTime);
            if (timeDifference <= 0) {
                //已到解封时间
                freeze.setIsFreezing(1);//1解冻，2冻结
                freeze.setReasonsForThawing(DateUtil.now()+"到期自动解冻~");
                freezeApi.updateById(freeze);
                this.movements(textContent, imageContents);
            } else {
                //当前用户被冻结
                throw new BusinessException(ErrorResult.FreezeMovementError(freeze.getUnfreezeTime()));
            }
        }
    }
}
